package client_gui;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;

import utils.Constants;
import utils.ImageCreator;
import utils.MessageViewer;
import utils.ParameterValidator;
import utils.RSA_Password;


/**
 * Klasa koja predstavlja LoginPanel, odakle se aktivira proces logovanja korisnika i
 * prelazak u logovan rezim rada klijent aplikacije, u slucaju uspesnog logovanja.
 * 
 * @author UrosKrkic & Radivoje Popovic
 */
public class LoginPanel extends JPanel implements Constants {

	/**
	 * Vlasnik - glavni prozor aplikacije.
	 */
	private ClientWindow owner;
	
	
	/**
	 * Layout manager - GridBagLayout
	 */
	private GridBagLayout gridBag = null;
	
	
	// ogranicenja u GridBagLayout-u
	private GridBagConstraints usernameLabelConstraint = null;
	private GridBagConstraints usernameFieldConstraint = null;
	private GridBagConstraints passwordLabelConstraint = null;
	private GridBagConstraints passwordFieldConstraint = null;
	private GridBagConstraints statusLabelConstraint = null;
//	private GridBagConstraints statusComboConstraint = null;
	private GridBagConstraints statusButtonConstraint = null;
	private GridBagConstraints loginButtonConstraint = null;
	private GridBagConstraints rememberUsernameChkConstraint = null;
	private GridBagConstraints rememberPasswordChkConstraint = null;
	
	
	/**
	 * Border.
	 */
	private TitledBorder titledBorder;
	
	
	// komponente ovog panela
	private JLabel usernameLabel = null;
	private JTextField usernameField = null;
	private JLabel passwordLabel = null;
	private JPasswordField passwordField = null;
	private JLabel statusLabel = null;
	private JButton statusButton = null;
	private JButton loginButton = null;
	private JCheckBox rememberUsernameCheckkBox = null;
	private JCheckBox rememberPasswordCheckkBox = null;
	
	
	
	/**
	 * Konstruktor.
	 * @param owner - glavni prozor aplikacije
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public LoginPanel(ClientWindow owner) {
		this.owner = owner;
		
		this.gridBag = new GridBagLayout();
		
		usernameLabelConstraint = new GridBagConstraints();
		usernameFieldConstraint = new GridBagConstraints();
		passwordLabelConstraint = new GridBagConstraints();
		passwordFieldConstraint = new GridBagConstraints();
		statusLabelConstraint = new GridBagConstraints();
		statusButtonConstraint = new GridBagConstraints();
		loginButtonConstraint = new GridBagConstraints();
		rememberUsernameChkConstraint = new GridBagConstraints();
		rememberPasswordChkConstraint = new GridBagConstraints();
		
		
		titledBorder = BorderFactory.createTitledBorder(BorderFactory.
				createEtchedBorder(EtchedBorder.RAISED),
				"Login", javax.swing.border.TitledBorder.CENTER,
				javax.swing.border.TitledBorder.DEFAULT_POSITION,
				null, null);
		
		
		initializeLoginPanel();
	}
	
	
	
	/**
	 * Metod vrsi inicijalizaciju ovog panela.
	 * @author UrosKrkic & Radivoje Popovic
	 */
	private void initializeLoginPanel() {
		this.setLayout(gridBag);
		this.setBorder(titledBorder);
		
		// inicijalizacija ogranicenja LayoutManager-a
		initializeConstraints();
		
		// dodavanje komponenti u panel
		this.add(getUsernameLabel());
		this.add(getUsernameField());
		this.add(getPasswordLabel());
		this.add(getPasswordField());
		this.add(getStatusLabel());
		this.add(getStatusButton());
		this.add(getRememberUsernameCheckBox());
		this.add(getRememberPasswordCheckBox());
		this.add(getLoginButton());
	}
	
	
	
	/**
	 * Metod vrsi inicijalizaciju ogranicenja LayoutManager-a.
	 * @author UrosKrkic & Radivoje Popovic
	 */
	private void initializeConstraints() {
		usernameLabelConstraint.gridx = 0;
		usernameLabelConstraint.gridy = 0;
		usernameLabelConstraint.weightx = 1;
		usernameLabelConstraint.weighty = 1;
		usernameLabelConstraint.anchor = GridBagConstraints.NORTHWEST;
		usernameLabelConstraint.insets = new Insets(10,10,20,10);
		
		usernameFieldConstraint.gridx = 1;
		usernameFieldConstraint.gridy = 0;
		usernameFieldConstraint.weightx = 1;
		usernameFieldConstraint.weighty = 1;
		usernameFieldConstraint.anchor = GridBagConstraints.NORTHWEST;
		usernameFieldConstraint.insets = new Insets(10,0,20,10);
		
		passwordLabelConstraint.gridx = 0;
		passwordLabelConstraint.gridy = 1;
		passwordLabelConstraint.weightx = 1;
		passwordLabelConstraint.weighty = 1;
		passwordLabelConstraint.anchor = GridBagConstraints.NORTHWEST;
		passwordLabelConstraint.insets = new Insets(0,10,20,10);
		
		passwordFieldConstraint.gridx = 1;
		passwordFieldConstraint.gridy = 1;
		passwordFieldConstraint.weightx = 1;
		passwordFieldConstraint.weighty = 1;
		passwordFieldConstraint.anchor = GridBagConstraints.NORTHWEST;
		passwordFieldConstraint.insets = new Insets(0,0,20,10);
		
		statusLabelConstraint.gridx = 0;
		statusLabelConstraint.gridy = 2;
		statusLabelConstraint.weightx = 1;
		statusLabelConstraint.weighty = 1;
		statusLabelConstraint.anchor = GridBagConstraints.NORTHWEST;
		statusLabelConstraint.insets = new Insets(0,10,50,10);
		
		statusButtonConstraint.gridx = 1;
		statusButtonConstraint.gridy = 2;
		statusButtonConstraint.weightx = 1;
		statusButtonConstraint.weighty = 1;
		statusButtonConstraint.anchor = GridBagConstraints.NORTHWEST;
		statusButtonConstraint.insets = new Insets(0,0,50,10);
		
		rememberUsernameChkConstraint.gridx = 1;
		rememberUsernameChkConstraint.gridy = 3;
		rememberUsernameChkConstraint.weightx = 1;
		rememberUsernameChkConstraint.weighty = 1;
		rememberUsernameChkConstraint.anchor = GridBagConstraints.NORTHWEST;
		rememberUsernameChkConstraint.insets = new Insets(0,0,20,10);

		rememberPasswordChkConstraint.gridx = 1;
		rememberPasswordChkConstraint.gridy = 4;
		rememberPasswordChkConstraint.weightx = 1;
		rememberPasswordChkConstraint.weighty = 1;
		rememberPasswordChkConstraint.anchor = GridBagConstraints.NORTHWEST;
		rememberPasswordChkConstraint.insets = new Insets(0,0,70,10);
		
		
		loginButtonConstraint.gridx = 1;
		loginButtonConstraint.gridy = 5;
		loginButtonConstraint.weightx = 1;
		loginButtonConstraint.weighty = 1;
		loginButtonConstraint.anchor = GridBagConstraints.NORTHWEST;
		loginButtonConstraint.insets = new Insets(0,0,20,10);
	}
	
	
	
	
	// Metode koje inicijalizuju komponente ovog panela.
	
	private JLabel getUsernameLabel() {
		if (usernameLabel == null) {
			usernameLabel = new JLabel("Username:");
			gridBag.setConstraints(usernameLabel, usernameLabelConstraint);
		}
		
		return usernameLabel;
	}
	
	
	private JTextField getUsernameField() {
		if (usernameField == null) {
			usernameField = new JTextField();
			usernameField.setPreferredSize(new Dimension(170,20));
			gridBag.setConstraints(usernameField, usernameFieldConstraint);
		}
		
		return usernameField;
	}
	
	
	private JLabel getPasswordLabel() {
		if (passwordLabel == null) {
			passwordLabel = new JLabel("Password:");
			gridBag.setConstraints(passwordLabel, passwordLabelConstraint);
		}
		
		return passwordLabel;
	}
	
	
	private JPasswordField getPasswordField() {
		if (passwordField == null) {
			passwordField = new JPasswordField();
			passwordField.setPreferredSize(new Dimension(170,20));
			gridBag.setConstraints(passwordField, passwordFieldConstraint);
			passwordField.addKeyListener(new KeyAdapter() {
				public void keyPressed(KeyEvent e) {
					if (e.getKeyCode() == KeyEvent.VK_ENTER) {
						loginButton.doClick();
					}
				}
			});
		}
		
		return passwordField;
	}
	
	
	private JLabel getStatusLabel() {
		if (statusLabel == null) {
			statusLabel = new JLabel("Status:");
			gridBag.setConstraints(statusLabel, statusLabelConstraint);
		}
		
		return statusLabel;
	}
	
	
	private JButton getStatusButton() {
		if (statusButton == null) {
			statusButton = new JButton(STATUS_NAMES[ONLINE_STATUS]);
			statusButton.setToolTipText("Izbor Statusa");
			statusButton.setIcon(ImageCreator.createImageIcon(LoginPanel.class, "/status_images/" + STATUS_NAMES[ONLINE_STATUS] + ".png"));
			statusButton.setMargin(new Insets(0,2,0,2));
			statusButton.setPreferredSize(new Dimension(80,25));
//			statusButton.setBackground(new Color(178, 223, 238));
			gridBag.setConstraints(statusButton, statusButtonConstraint);
			
			statusButton.addMouseListener(new MouseAdapter() {
				@Override
				public void mouseReleased(MouseEvent e) {
					
					int x = 0;
					int y = statusButton.getHeight();
					
					owner.getStatusContexMenu().show((Component)e.getSource(), x, y);
				}
			});
		}
		
		return statusButton;
	}
	
	
	private JButton getLoginButton() {
		if (loginButton == null) {
			loginButton = new JButton(owner.getActionManager().getLoginAction());
			loginButton.setText("Login");
			loginButton.setToolTipText("Logovanje korisnika");
			loginButton.setPreferredSize(new Dimension(100,25));
			gridBag.setConstraints(loginButton, loginButtonConstraint);
		}
		
		return loginButton;
	}
	
	
	private JCheckBox getRememberUsernameCheckBox() {
		if (rememberUsernameCheckkBox == null) {
			rememberUsernameCheckkBox = new JCheckBox("Remember Me");
			gridBag.setConstraints(rememberUsernameCheckkBox, rememberUsernameChkConstraint);
		}
		
		return rememberUsernameCheckkBox;
	}
	
	
	private JCheckBox getRememberPasswordCheckBox() {
		if (rememberPasswordCheckkBox == null) {
			rememberPasswordCheckkBox = new JCheckBox("Rememeber my Password");
			gridBag.setConstraints(rememberPasswordCheckkBox, rememberPasswordChkConstraint);
			rememberPasswordCheckkBox.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					if (rememberPasswordCheckkBox.isSelected() == true) {
						rememberUsernameCheckkBox.setSelected(true);
					}
				}
			});
		}
		
		return rememberPasswordCheckkBox;
	}

	
	/**
	 * Metod postavlja username, password i status iz ovog panela kao atribute
	 * ClientUser objekta, koji predstavlja korisnika koji je pokrenuo klijent
	 * aplikaciju i koji zeli da se loguje. 
	 * @author UrosKrkic & Radivoje Popovic
	 */
	public boolean createPartialLoginInfo() {
		
		ParameterValidator.setRegex(ParameterValidator.usernameRegExp);
		
		if ( !ParameterValidator.matchStrings(usernameField.getText())) {
			MessageViewer.showError(owner, "Bad or too long Username (max. 15 chars.)");
			return false;
		}
		
		ParameterValidator.setRegex(ParameterValidator.passwordRegExp);
		
		if ( !ParameterValidator.matchStrings(new String(passwordField.getPassword())) ) {
			MessageViewer.showError(owner, "Bad or too long Password (max. 15 chars.)");
			return false;
		}
		
		
		// objekat za kriptovanje password-a
		RSA_Password rsa = new RSA_Password();
		
		owner.getApplicaton().getClientUser().setUsername(usernameField.getText());
		owner.getApplicaton().getClientUser().setPassword(rsa.codeData(new String(passwordField.getPassword())));
		String statusTemp = statusButton.getText();

		int status = 0;
		for (int i = 0; i < STATUS_NAMES.length; i++) {
			if ( statusTemp.equals(STATUS_NAMES[i]) ) {
				status = i;
				break;
			}
		}
		owner.getApplicaton().getClientUser().setStatus(status);
	
		return true;
	}

	
	
	
	public void setInitialStatus(String status) {
		statusButton.setText(status);
		statusButton.setIcon(ImageCreator.createImageIcon(LoginPanel.class, "/status_images/" + status + ".png"));
	}
	
	
	public void setLoginUsername(String username) {
		this.usernameField.setText(username);
	}
	
	
	public void setLoginPassword(String password) {
		this.passwordField.setText(password);
	}

	
	public void setUsernameCheckBox(boolean flag) {
		rememberUsernameCheckkBox.setSelected(flag);
	}
	
	
	public void setPasswordCheckBox(boolean flag) {
		rememberPasswordCheckkBox.setSelected(flag);
	}
	
	public boolean isUsernameCheckBoxSelected() {
		return rememberUsernameCheckkBox.isSelected();
	}
	
	public boolean isPasswordCheckBoxSelected() {
		return rememberPasswordCheckkBox.isSelected();
	}
	
}
